﻿using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Collections.Specialized;
using System.Collections.Generic;

public partial class SlabStructure : System.Web.UI.Page
{
    #region page member & method
    private static SlabsTable matrix;
    private static String SELECT_FORMULA = "20";

    protected void Page_Init(object sender, EventArgs e)
    {
        if (matrix != null)
        {
            createMatrixStructure();
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            ManageEditables(false);
            if (LBSlabs.SelectedIndex < 0)
                BEdit.Visible = false;
        }
    }
    #endregion

    #region retrieve the data on initialization
    protected void LBSlabs_SelectedIndexChanged(object sender, EventArgs e)
    {
        //clear it before display
        PanelTable.Controls.Clear();

        matrix = new SlabsTable(Convert.ToInt32(LBSlabs.SelectedValue));
        retrieveSlabDetails();
        createMatrixStructure();
        loadMatrix();
        ManageEditables(false);
    }

    private void retrieveSlabDetails()
    {
        DataRow slab = SlabsDisplay.getSlabRow(Convert.ToInt32(LBSlabs.SelectedValue));

        //set upper values
        TextBoxName.Text = slab["Name"].ToString();
        TBFromDate.Text = Convert.ToDateTime(slab["FromDate"].ToString()).ToString(GlobalVariables.DateFormat);
        TBToDate.Text = Convert.ToDateTime(slab["ToDate"].ToString()).ToString(GlobalVariables.DateFormat);
        DDLRowRelOp.SelectedValue = slab["ROperator"].ToString();
        DDLColumnRelOp.SelectedValue = slab["COperator"].ToString();
        DDLSteppedTired.SelectedValue = slab["IsStepped"].ToString().Trim();
        DDLFunctionR.SelectedValue = slab["RFormula"].ToString();
        DDLFunctionC.SelectedValue = slab["CFormula"].ToString();

        //set dimensions
        DDLRowCount.SelectedValue = matrix.getRowCount().ToString();
        DDLColumnCount.SelectedValue = matrix.getColumnCount().ToString();
    }

    private void ManageEditables(bool editable)
    {
        //manage buttons
        BApply.Visible = editable;
        BCancel.Visible = editable;
        BEdit.Visible = !editable;
        BCreate.Visible = !editable;

        //manage panels
        panelMiddleInner.Enabled = editable;
        PanelUpper.Enabled = editable;

        //formula for  column
        if (DDLColumnCount.SelectedValue.ToString() == "1")
            DDLColumnRelOp.Enabled = DDLFunctionC.Enabled = false;
        else
            DDLColumnRelOp.Enabled = DDLFunctionC.Enabled = true;
    }

    protected void DDLColumnCount_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (Convert.ToInt32(DDLColumnCount.SelectedValue) > 1)
        {
            DDLColumnRelOp.Enabled = true;
            DDLFunctionC.Enabled = true;
        }
        else
        {
            DDLColumnRelOp.Enabled = false;
            DDLFunctionC.Enabled = false;
            DDLFunctionC.SelectedValue = SELECT_FORMULA;
        }
    }
    #endregion

    #region button clicks
    protected void BEdit_Click(object sender, EventArgs e)
    {
        ManageEditables(true);
        //PanelUpper.Enabled = false;
    }

    protected void BCancel_Click(object sender, EventArgs e)
    {
        if (LBSlabs.SelectedIndex < 0)
        {
            ManageEditables(false);
            resetValues();
            return;
        }
        LBSlabs_SelectedIndexChanged(sender, e);
    }

    protected void BCreate_Click(object sender, EventArgs e)
    {
        matrix = null;
        ManageEditables(true);
        resetValues();
    }

    private void resetValues()
    {
        TextBoxName.Text = String.Empty;
        TBFromDate.Text = String.Empty;
        TBToDate.Text = String.Empty;

        DDLRowCount.SelectedValue = "5"; DDLColumnCount.SelectedValue = "1";
        DDLRowRelOp.SelectedValue = ">"; DDLColumnRelOp.SelectedValue = "=";
        DDLFunctionR.SelectedValue = DDLFunctionC.SelectedValue = SELECT_FORMULA;
        DDLSteppedTired.SelectedValue = "Stepped";

        panelMiddleInner.Controls.Clear();
        panelMiddleInner.Enabled = false;
    }

    protected void BApply_Click(object sender, EventArgs e)
    {
        //perform validations
        if (!arePageElementsValid())
            return;

        //slab details are non-updatable, so update them only when its new
        int slab_id = updateSlabsTable();

        //create and insert matrix
        int rows = Convert.ToInt32(DDLRowCount.SelectedValue.ToString());
        int cols = Convert.ToInt32(DDLColumnCount.SelectedValue.ToString());
        string rop = DDLRowRelOp.SelectedValue.ToString();
        string cop = DDLColumnRelOp.SelectedValue.ToString();

        //if its creating new, store to db directly
        if (matrix == null)
            matrix = new SlabsTable(slab_id, rows, rop, cols, cop);
        else //else update
            matrix.updateMatrix2DB(saveMatrix());

        //bind the data and then display
        LBSlabs.DataBind();
        LBSlabs.SelectedValue = slab_id.ToString();
        LBSlabs_SelectedIndexChanged(sender, e);

        return;
    }

    private int updateSlabsTable()
    {
        //retieve values to insert
        NameValueCollection nvc = SlabsDisplay.getNVC4Slabs();
        nvc.Set("Name", TextBoxName.Text.ToString());
        nvc.Set("FromDate", Convert.ToDateTime(TBFromDate.Text.ToString()).ToString(GlobalVariables.DateFormat));
        nvc.Set("ToDate", Convert.ToDateTime(TBToDate.Text.ToString()).ToString(GlobalVariables.DateFormat));
        nvc.Set("Dimension", Convert.ToInt64(DDLColumnCount.SelectedValue) > 1 ? "2" : "1"); //1D or 2D
        nvc.Set("ROperator", DDLRowRelOp.SelectedValue.ToString());
        nvc.Set("COperator", DDLColumnRelOp.SelectedValue.ToString());
        nvc.Set("IsStepped", DDLSteppedTired.SelectedValue.ToString());
        nvc.Set("RFormula", DDLFunctionR.SelectedValue.ToString());
        nvc.Set("CFormula", DDLFunctionC.SelectedValue.ToString());

        if (matrix != null) //update existing entry
        {
            List<String> key = new List<String> { "RowNo" };
            nvc.Add("RowNo", matrix.getSlabId().ToString());
            string updateQ = DataBaseMethods.generateUpdateQuery("Slabs", nvc, key);
            DataBaseMethods.ExecuteNonQuery(updateQ);
            return matrix.getSlabId();
        }
        else //insert
        {
            string insertCommand = DataBaseMethods.generateInsertQuery("Slabs", nvc);
            return DataBaseMethods.ExecuteIdentityInsert(insertCommand, "RowNo");
        }
    }
    #endregion

    #region create table for matrix display
    private void createMatrixStructure()
    {
        //create non-header part
        for (int i = 0; i < matrix.getRowCount(); i++)
        {
            TableRow row = new TableRow();
            for (int j = 0; j < matrix.getColumnCount(); j++)
            {
                TableCell column = new TableCell();
                column.Controls.Add(getNonHeaderTextBox(i, j));
                row.Cells.Add(column);
            } //column loop
            PanelTable.Rows.Add(row);
        }

        //add headers also
        addHeaders();

        return;
    }

    private void addHeaders()
    {
        //add column header for 2d only
        if (matrix.getColumnCount() > 1)
        {
            //add column headers
            TableHeaderRow hrow = new TableHeaderRow();
            for (int i = 0; i < matrix.getColumnCount(); i++)
                hrow.Cells.Add(getHeaderCell(matrix.getCOper()));
            PanelTable.Rows.AddAt(0, hrow);

            //display HEADER at position 0,0
            TextBox tb = getNonHeaderTextBox(-1, -1);
            tb.Text = "Header";
            tb.Enabled = false;
            TableCell zzCell = new TableCell();
            zzCell.Controls.Add(tb);
            PanelTable.Rows[0].Cells.AddAt(0, zzCell);

            for (int i = 1; i <= matrix.getRowCount(); i++)
                PanelTable.Rows[i].Cells.AddAt(0, getHeaderCell(matrix.getROper()));
        }
        else    //add row header 1d
        {
            for (int i = 0; i < matrix.getRowCount(); i++)
                PanelTable.Rows[i].Cells.AddAt(0, getHeaderCell(matrix.getROper()));
        }
        return;
    }

    private TableCell getHeaderCell(string oper)
    {
        TableCell hCell = new TableCell();

        //tb for sign
        TextBox tb1 = new TextBox();
        tb1.Width = 20;
        tb1.Text = oper;
        tb1.Enabled = false;
        tb1.BackColor = System.Drawing.Color.Aqua;
        hCell.Controls.Add(tb1);

        //tb for value
        TextBox tb2 = new TextBox();
        tb2.Width = 60;
        tb2.BackColor = System.Drawing.Color.Aqua;
        hCell.Controls.Add(tb2);

        return hCell;
    }

    private TextBox getNonHeaderTextBox(int r, int c)
    {
        TextBox tb = new TextBox();
        tb.Width = 82;
        tb.ID = "TextBox_" + r.ToString() + c.ToString();
        return tb;
    }
    #endregion

    #region converts matrix v/s flat
    private void loadMatrix()
    {
        DataTable flatDt = matrix.getFlatMatrix();
        foreach (DataRow dr in flatDt.Rows)
        {
            int r = Convert.ToInt32(dr["RowNo"].ToString());
            int c = Convert.ToInt32(dr["ColumnNo"].ToString());
            string value = dr["Value"].ToString();

            TableCell tc = PanelTable.Rows[r].Cells[c];
            ControlCollection cc = tc.Controls;
            for (int i = 0; i < tc.Controls.Count; i++)
            {
                if (tc.Controls[i] is TextBox)
                {
                    TextBox tb = (TextBox)tc.Controls[i];
                    if (!tb.Enabled) continue;
                    if ((r == 0) || (c == 0))
                        tb.Text = value;
                    else
                        tb.Text = Convert.ToDouble(value).ToString();
                }
            }
        }//done with row

        return;
    }

    private DataTable saveMatrix()
    {
        DataTable flatDt = matrix.getFlatMatrix();
        foreach (DataRow dr in flatDt.Rows)
        {
            int r = Convert.ToInt32(dr[1].ToString());
            int c = Convert.ToInt32(dr[2].ToString());

            TableCell tc = PanelTable.Rows[r].Cells[c];
            ControlCollection cc = tc.Controls;
            for (int i = 0; i < tc.Controls.Count; i++)
            {
                if (tc.Controls[i] is TextBox)
                {
                    TextBox tb = (TextBox)tc.Controls[i];
                    if (!tb.Enabled) continue;
                    try
                    {
                        dr[3] = Convert.ToDouble(tb.Text).ToString();
                    }
                    catch (Exception)
                    {
                        dr[3] = "0";
                        if ((r == 0) || (c == 0))
                            dr[3] = tb.Text;
                    }
                }
            }
        } // done with row

        flatDt.AcceptChanges();
        return flatDt;
    }
    #endregion

    #region load data in dropdowns
    protected void DDLSteppedTired_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DDLSteppedTired.DataSource = SlabsDisplay.SteppedTiered();
            DDLSteppedTired.DataBind();
            DDLSteppedTired.SelectedValue = "Stepped";
        }
    }

    protected void DDLFunctionC_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            String query = SlabsDisplay.formulaListQuery();
            DataTable dt = DataBaseMethods.ExecuteSelectQuery(query);
            DDLFunctionC.DataSource = dt;
            DDLFunctionC.DataBind();
            DDLFunctionC.SelectedValue = SELECT_FORMULA;
        }
    }

    protected void DDLFunctionR_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            String query = SlabsDisplay.formulaListQuery();
            DataTable dt = DataBaseMethods.ExecuteSelectQuery(query);
            DDLFunctionR.DataSource = dt;
            DDLFunctionR.DataBind();
            DDLFunctionR.SelectedValue = SELECT_FORMULA;
        }
    }

    protected void DDLColumnRelOp_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DDLColumnRelOp.DataSource = SlabsDisplay.Operators();
            DDLColumnRelOp.DataBind();
            DDLColumnRelOp.SelectedValue = "=";
        }
    }

    protected void DDLRowRelOp_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DDLRowRelOp.DataSource = SlabsDisplay.Operators();
            DDLRowRelOp.DataBind();
            DDLRowRelOp.SelectedValue = ">";
        }
    }

    protected void DDLColumnCount_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DDLColumnCount.DataSource = SlabsDisplay.Dimensions();
            DDLColumnCount.DataBind();
            DDLColumnCount.SelectedValue = "1";
        }
    }

    protected void DDLRowCount_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DDLRowCount.DataSource = SlabsDisplay.Dimensions();
            DDLRowCount.DataBind();
            DDLRowCount.SelectedValue = "5";
        }
    }
    #endregion

    #region validations
    protected Boolean arePageElementsValid()
    {
        if ((String.IsNullOrEmpty(TBFromDate.Text) || String.IsNullOrEmpty(TBToDate.Text) || String.IsNullOrWhiteSpace(TextBoxName.Text) ))
        {
            Logger.Show(Logger.MANDATORY_FIELD);
            return false;
        }

        if ( ( DDLFunctionR.SelectedValue == SELECT_FORMULA ) || 
            ((Convert.ToInt32(DDLColumnCount.SelectedValue) > 1) && (DDLFunctionC.SelectedValue == SELECT_FORMULA) ))
        {
            Logger.Show(Logger.SELECT_FORMULA);
            return false;
        }

        return true;
    }

    protected void TextBoxName_TextChanged(object sender, EventArgs e)
    {
        String mode = (matrix == null ? "create" : "update");
        if (!GenericValidations.isValidName(TextBoxName.Text, LBSlabs.Items, mode))
            TextBoxName.Text = String.Empty;
        return;
    }

    protected void TBFromDate_TextChanged(object sender, EventArgs e)
    {
        //check date & also range
        if (!GenericValidations.validateFromToDates(TBFromDate.Text, TBToDate.Text))
            TBFromDate.Text = String.Empty;
        return;
    }

    protected void TBToDate_TextChanged(object sender, EventArgs e)
    {
        //check date & also range
        if (!GenericValidations.validateFromToDates(TBFromDate.Text, TBToDate.Text))
            TBToDate.Text = String.Empty;
        return;
    }
    #endregion

}
